#ifndef _SD_UPDATE_
#define _SD_UPDATE_
#include "hisi6421.h"

/*error code*/
#define SD_STATUS_SUCCESS                         0
#define SD_STATUS_CHECKBPB_ERR                    0x80000001
#define SD_STATUS_READFILEFAT_ERR                 0x80000002
#define SD_STATUS_FIND_NOFILE                     0x80000003
#define SD_STATUS_WRONGNAME                       0x80000004
#define SD_STATUS_SEEK_ERR                        0x80000005
#define SD_STATUS_IMGFILE_NUM_ERR                 0x80000006
#define SD_STATUS_IMGFILE_LEN_ERR                 0x80000007
#define SD_STATUS_MDM_ERASR_ERR                   0x80000008
#define SD_STATUS_MDM_LOAD_ERR                    0x80000009
#define SD_STATUS_MDM_WRITE_ERR                   0x8000000A
#define SD_STATUS_BLOCKALLBAD_ERR                 0x8000000B
#define SD_STATUS_NOCARD_EXIST                    0x8000000C
#define SD_STATUS_IMG_CRC_ERR                     0x8000000D
#define SD_STATUS_VERSION_ERR                     0x8000000E
#define SD_STATUS_PATOVA_ERR                      0x8000000F
#define SD_STATUS_BATTERY_ERR                     0x80000010
#define SD_STATUS_MEMMAP_ERR                      0x80000011
#define SD_STATUS_RESP_ERR                        0x80000012
#define SD_STATUS_DATAREAD_TMOUT                  0x80000013
#define SD_STATUS_DATAREAD_RETRY_TMOUT            0x80000014
#define SD_STATUS_DATABUSY_TOOLONG_ERR            0x80000015
#define SD_STATUS_POLLCMD_ERR                     0x80000016
#define SD_STATUS_INTR_HANDLE_ERR                 0x80000017
#define SD_STATUS_INTR_MISS_ERR                   0x80000018
#define SD_STATUS_RESP_TMOUT                      0x80000019
#define SD_STATUS_VOLTAB_ERR                      0x8000001A

/*file attributes*/
#define ATTR_READ_ONLY   	                      0x01
#define ATTR_HIDDEN 	                          0x02
#define ATTR_SYSTEM 	                          0x04
#define ATTR_VOLUME_ID 	                          0x08
#define ATTR_DIRECTORY	                          0x10
#define ATTR_ARCHIVE  	                          0x20
#define ATTR_LONG_NAME 	                          (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID)

#define LAST_LONG_ENTRY  	                      0x40

#define LONG_DIR_ENTRY_NAME1LENGTH                10
#define LONG_DIR_ENTRY_NAME2LENGTH                12
#define LONG_DIR_ENTRY_NAME3LENGTH                4
#define LONG_DIR_ENTRY_ALLNAMELENGTH              (LONG_DIR_ENTRY_NAME1LENGTH+LONG_DIR_ENTRY_NAME2LENGTH+LONG_DIR_ENTRY_NAME3LENGTH)

#define  HEAD_SHORT_NAME_LENGTH                   8
#define  SHORT_NAME_LENGTH                        11

#define  FAT32_ITEM_PER_SECTOR                    128

//storage card macro
#define  SD_SECTOR_SIZE                           512
#define  MAX_SECTOR_NUMBERS                       64
#define  MAX_LONG_NAME_LENGTH                     1024

//FLASH macro defination
#define  SECTORINFO_SIZE                          8
#define  SECTORSIZE_WITH_SECTORINFO               (SECTORINFO_SIZE + FLASH_SECTOR_SIZE)
#define  BLOCKSIZE_WITH_SECTORINFO                (SECTORSIZE_WITH_SECTORINFO*FLASH_SECTOR_NUMBERS)

//sd request type
#define SD_CMD_READ                               0
#define SD_CMD_WRITE                              1
#define SD_CMD_COMMAND                            2

//sd request response length
#define MAX_RESPONSE_LENGTH                       16

/**/
#pragma  pack(1)
typedef struct
{
    UINT8 ActFlag;  
    UINT8 StartHead;
    UINT8 StartSec; /*actually sector = StartSec & 0x3f*/ 
    UINT8 StartCyl; /*actually cylinder = (StartSec & 0xc0)<<2 + StartCyl*/
    UINT8 SysFlag;  /*file system type*/
    UINT8 EndHead;
    UINT8 EndSec;
    UINT8 EndCyl;
    UINT32 StartSecNo;
    UINT32 VolSize;     /*in sector*/
}VOL_TAB;

typedef struct _BOOT_SEC
{
    UINT8    jmpBoot[3];    /**/
    INT8     OEMName[8];    /**/
    UINT16   BytsPerSec;    /*512, 1024, 2048, 4096*/
    UINT8    SecPerClus;    /*The legal values are 1, 2, 4, 8, 16, 32, 64, and 128. Note however, that a value should never be used that results in a "bytes per cluster" value (BPB_BytsPerSec * BPB_SecPerClus) greater than 32K (32 * 1024).*/
    UINT16   RsvdSecCnt;    /*Number of reserved sectors in the Reserved region of the volume starting at the first sector of the volume. This field must not be 0. For FAT12 and FAT16 volumes, this value should never be anything other than 1. For FAT32 volumes, this value is typically 32.*/
    UINT8    NumFATs;    /*The count of FAT data structures on the volume. This field should always contain the value 2 for any FAT volume of any type. */
    UINT16   RootEntCnt;    /*For FAT12 and FAT16 volumes, this field contains the count of 32-byte directory entries in the root directory. For FAT32 volumes, this field must be set to 0. For FAT12 and FAT16 volumes, this value should always specify a count that when multiplied by 32 results in an even multiple of BPB_BytsPerSec. For maximum compatibility, FAT16 volumes should use the value 512*/
    UINT16   TotSec16;    /**/
    UINT8    Media;    /*0xF8 is the standard value for "fixed" (non-removable) media. For removable media, 0xF0 is frequently used. The legal values for this field are 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, and 0xFF. The only other important point is that whatever value is put in here must also be put in the low byte of the FAT[0] entry. This dates back to the old MS-DOS 1.x media determination noted earlier and is no longer usually used for anything.*/
    UINT16   FATSz16;    /*in sector*/
    UINT16   SecPerTrk;    /*Sectors per track for interrupt 0x13. This field is only relevant for media that have a geometry (volume is broken down into tracks by multiple heads and cylinders) and are visible on interrupt 0x13. This field contains the "sectors per track" geometry value.*/
    UINT16   NumHeads;    /*Number of heads for interrupt 0x13. This field is relevant as discussed earlier for BPB_SecPerTrk. This field contains the one based "count of heads". For example, on a 1.44 MB 3.5-inch floppy drive this value is 2.*/
    UINT32   HiddSec;    /*Count of hidden sectors preceding the partition that contains this FAT volume. This field is generally only relevant for media visible on interrupt 0x13. This field should always be zero on media that are not partitioned. Exactly what value is appropriate is operating system specific*/
    UINT32   TotSec32 ;    /**/
    union _BPBEXT_
    {
        struct _FAT16_PACKED
        {
            UINT8   DrvNum;   /*Int 0x13 drive number (e.g. 0x80). This field supports MS-DOS bootstrap and is set to the INT 0x13 drive number of the media (0x00 for floppy disks, 0x80 for hard disks). */
            UINT8   Reserved1;   /*0*/
            UINT8   BootSig;   /*Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.*/
            UINT32  VolID;   /*Volume serial number. This field, together with BS_VolLab, supports volume tracking on removable media.This ID is usually generated by simply combining the current date and time into a 32-bit value.*/
            UINT8   VolLab[11];   /*Volume label. This field matches the 11-byte volume label recorded in the root directory. The setting for this field when there is no volume label is the string "NO NAME    ".*/
            UINT8   FilSysType[8];   /*One of the strings "FAT12   ", "FAT16   ", or "FAT     ".  */
            UINT8   BootCode[448];    /*boot code*/
        }
        Fat16;
        struct _FAT32_PACKED
        {
            UINT32   FATSz32;   /*in sector*/
            /*This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media.
            Bits 0-3	-- Zero-based number of active FAT. Only valid if mirroring is disabled.
            Bits 4-6	-- Reserved.
            Bit      7	-- 0 means the FAT is mirrored at runtime into all FATs.
            	-- 1 means only one FAT is active; it is the one referenced in bits 0-3.
            Bits 8-15 	-- Reserved.
            */
            UINT16   ExtFlags;
            UINT16   FSVer;   /* High byte is major revision number. Low byte is minor revision number. This document defines the version to 0:0*/
            UINT32   RootClus;   /*This is set to the cluster number of the first cluster of the root directory, usually 2 but not required to be 2. */
            UINT16   FSInfo;   /*Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. */
            UINT16   BkBootSec;   /* If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. No value other than 6 is recommended.*/
            UINT8    Reserved[12];   /*0*/
            UINT8    DrvNum;   /*Int 0x13 drive number (e.g. 0x80). This field supports MS-DOS bootstrap and is set to the INT 0x13 drive number of the media (0x00 for floppy disks, 0x80 for hard disks). */
            UINT8    Reserved1;   /*0*/
            UINT8    BootSig;   /*Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.*/
            UINT32   VolID;   /*Volume serial number. This field, together with BS_VolLab, supports volume tracking on removable media.This ID is usually generated by simply combining the current date and time into a 32-bit value.*/
            UINT8    VolLab[11];   /*Volume label. This field matches the 11-byte volume label recorded in the root directory. The setting for this field when there is no volume label is the string "NO NAME    ".*/
            UINT8    FilSysType[8];   /*One of the strings "FAT12   ", "FAT16   ", or "FAT     ".  */
            UINT8    BootCode[420];    /*boot code*/
        }
        Fat32;
    } BpbExt;
    UINT16  CloseFlag;    /*0xaa55*/
}
BOOT_SEC, *PBOOT_SEC;

typedef struct _FS_INFO
{
    UINT32   LeadSig;   /*0x41615252*/
    UINT8    Reserved1[480];   /*0*/
    UINT32   StrucSig;   /*Value 0x61417272. Another signature that is more localized in the sector to the location of the fields that are used*/
    UINT32   Free_Count;   /*Contains the last known free cluster count on the volume. If the value is 0xFFFFFFFF, then the free count is unknown and must be computed.*/
    UINT32   Nxt_Free;   /*This is a hint for the FAT driver. It indicates the cluster number at which the driver should start looking for free clusters. Because a FAT32 FAT is large, it can be rather time consuming if there are a lot of allocated clusters at the start of the FAT and the driver starts looking for a free cluster starting at cluster 2. Typically this value is set to the last cluster number that the driver allocated. If the value is 0xFFFFFFFF, then there is no hint and the driver should start looking at cluster 2.*/
    UINT8    Reserved2[12];   /*0*/
    UINT32   TrailSig;   /*0xAA550000*/
}
FS_INFO, *PFS_INFO;

typedef struct _DIR_ENTRY
{
    UINT8   Name[11];   /*Short name.*/
    /*    File attributes:
    ATTR_READ_ONLY   	0x01
    ATTR_HIDDEN 	0x02
    ATTR_SYSTEM 	0x04
    ATTR_VOLUME_ID 	0x08
    ATTR_DIRECTORY	0x10
    ATTR_ARCHIVE  	0x20
    ATTR_LONG_NAME 	ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID
    The upper two bits of the attribute byte are reserved and should always be set to 0 when a file is created and never modified or looked at after that.
    */
    UINT8    Attr;   /**/
    UINT8    NTRes;   /*0*/
    UINT8    CrtTimeTenth;   /*Millisecond stamp at file creation time. This field actually contains a count of tenths of a second. The granularity of the seconds part of DIR_CrtTime is 2 seconds so this field is a count of tenths of a second and its valid value range is 0-199 inclusive.*/
    UINT16   CrtTime;   /**/
    UINT16   CrtDate;   /**/
    UINT16   LstAccDate;   /*Last access date. Note that there is no last access time, only a date. */
    UINT16   FstClusHI;   /*High word of this entry's first cluster number (always 0 for a FAT12 or FAT16 volume).*/
    UINT16   WrtTime;   /*Time of last write. Note that file creation is considered a write.*/
    UINT16   WrtDate;   /*Date of last write. Note that file creation is considered a write.*/
    UINT16   FstClusLO;   /*Low word of this entry's first cluster number.*/
    UINT32   FileSize;   /*32-bit DWORD holding this file's size in bytes.*/
}
DIR_ENTRY, *PDIR_ENTRY;

typedef struct _LONG_DIR_ENTRY
{
    UINT8  Ord;    /*The order of this entry in the sequence of long dir entries associated with the short dir entry at the end of the long dir set.*/
    UINT8  Name1[LONG_DIR_ENTRY_NAME1LENGTH];  /*Characters 1-5 of the long-name sub-component in this dir entry.*/
    UINT8  Attr;  /*Attributes - must be ATTR_LONG_NAME*/
    UINT8  Type;  /*0*/
    UINT8  Chksum;  /*Checksum of name in the short dir entry at the end of the long dir set.*/
    UINT8  Name2[LONG_DIR_ENTRY_NAME2LENGTH];  /*Characters 6-11 of the long-name sub-component in this dir entry.*/
    UINT16 FstClusLO;  /*0*/
    UINT8  Name3[LONG_DIR_ENTRY_NAME3LENGTH];  /*Characters 12-13 of the long-name sub-component in this dir entry.*/
}
LONG_DIR_ENTRY, *PLONG_DIR_ENTRY;

#pragma  pack()

//FAT type
typedef enum
{
    FAT16       = 1,
    FAT32       = 2,
    FATUNKNOWN  = 3,
} FATTYPE;

//file position
typedef enum
{
    FILE_BEGIN_LOC    = 0,
    FILE_CURRENT_LOC  = 1,
    FILE_END_LOC      = 2,
    FILE_UNKNOWN_LOC  = 3,
}FILE_BASE_LOC;

//FAT info structure
typedef struct _FAT_INFO
{
    FATTYPE  fattype;        //
    DWORD    FATSz;
    DWORD    TotSec;
    DWORD    DataSec;
    DWORD    RootDirSectors;
    DWORD    CountofClusters;
    DWORD    FirstDataSector;
    DWORD    BPBStartSector;
    DWORD    FAT1StartSector;
    DWORD    FAT2StartSector;
    DWORD    ClusterSize;
    DWORD    FATNUMPERSEC;
    DWORD    FirstRootSector;
    DWORD    LastRootSector;
}
FAT_INFO, *PFAT_INFO;

//sd request structure
typedef struct _SD_BUS_COMMAND
{
    DWORD  TransferClass;                           // transfer class
    UCHAR  CommandCode;                             // command code
    DWORD  CommandArgument;                         // command argument
    ULONG  NumBlocks;                               // number of blocks
    ULONG  BlockSize;                               // size of each block
    PBYTE  pBlockBuffer;                            // buffer holding block data
    DWORD  ResponseType;                            // response type
    UCHAR  ResponseBuffer[MAX_RESPONSE_LENGTH+1];   // largest possible reponse buffer
}
SD_BUS_COMMAND, *PSD_BUS_COMMAND;

//sd request response type
typedef enum  _SD_RESPONSE_TYPE {
    NoResponse  = 0,
    ResponseR1  = 1,
    ResponseR1b = 2,
    ResponseR2  = 3,
    ResponseR3  = 4,
    ResponseR4  = 5,
    ResponseR5  = 6,
    ResponseR6  = 7,
    ResponseR7  = 8
}
SD_RESPONSE_TYPE, *PSD_RESPONSE_TYPE;


typedef enum {
    SD_MMC_1BIT = 0,
    SD_MMC_4BIT = 1,
} SD_DATA_MODE;

typedef struct _SD_CONTEXT_SET
{
    SD_DATA_MODE InterfaceMode;  // interface mode
    ULONG        ClockRate;      // clock rate
}
SD_CONTEXT_SET, *PSD_CONTEXT_SET;

DWORD ReadSector(PBYTE pData, DWORD dwStartSector, DWORD dwNumber);
DWORD SdCheckFile(PBYTE pFileName);
DWORD SdReadCurFile(PBYTE pData, DWORD dwLength);
DWORD SdSeekCurFile(DWORD dwOffset, FILE_BASE_LOC dwFileLocation);

#endif
